<?php 
namespace App\Service;

use App\Jobs\LoginRobotJob;
use App\lib\Api;
use App\Lib\CommonConf;
use App\Lib\Curl;
use App\Lib\StringHelper;
use App\Model\BotsModel;
use App\Model\FromTradeModel;
use App\Model\OutTradeModel;

class TradeService extends BaseService
{
	public static $instance = null;

    public $pickNum = 0;

    public static $confirmtradejobList = [
        'confirmtradejob',
        'confirmtradejob1',
        'confirmtradejob2',
    ];

	public static function getInstance()
	{
		if (self::$instance == null) {
			self::$instance = new self();
		}
		return self::$instance;
	}

    /**
     * 检测交易链接
     * @param $tradeUrl
     * @param $steamId
     * @param int $botId
     * @return array
     */
    public function checkTradeUrl($tradeUrl, $steamId, $botId=0)
    {
        if (!preg_match('/^https:\/\/steamcommunity.com\/tradeoffer\/new\/\?partner=(\d+)&token=([a-z0-9_\-]{1,20})$/i', $tradeUrl, $matches)) {
            return [Api::CODE_STEAM_TRADE_URL_FORMAT_ERROR, []];
        }

        $tradeToken = $matches[2];
        if (SteamUtilService::getInstance()->toCommunityID($matches[1]) != $steamId) {
            return [Api::CODE_STEAM_TRADE_URL_MATCH_ERROR, []];
        }

        if ($botId > 0) {
            $bot = BotsModel::getLivingBotByBotId($botId);
        } else {
            $bot = BotsModel::getCheckTradeUrlLivingBot();
        }

        if (empty($bot)) {
            return [Api::CODE_STEAM_TRADE_URL_SERVICE_BUSY, []];
        }

        $steam = $bot['steam'];
        if (empty($steam)  && $this->pickNum < 3) {
            $this->pickNum ++;
            $currentQueue = 'LoginRobotJob_' . $bot['client_no'];
            dispatch((new LoginRobotJob($bot['bot_id']))->onQueue($currentQueue)->delay(1));
            return $this->checkTradeUrl($tradeUrl, $steamId, $botId);
        }

        if (empty($steam)){
            return [Api::CODE_STEAM_TRADE_URL_LOADING_FAIL, []];
        }

        $response = $steam->cURL($tradeUrl);
        if (preg_match('/var\sg_daysMyEscrow\s=\s(\d+);\s+var\sg_daysTheirEscrow\s=\s(\d+);/', $response, $matches)) {
            if ($matches[2] > 0) {
                return [Api::CODE_STEAM_TRADE_URL_MOBILE_TOKEN_NEED_SEVEN_DAY, []];
            } else {
                return [Api::CODE_OK, ['tradeToken'=>$tradeToken, 'bot'=>$bot]];
            }
        } else {
            if ($response && strpos($response, '<div id="error_page_bg">') !== false) {
                return [Api::CODE_STEAM_TRADE_URL_INVALID_OR_INV_UNDISCLOSED, []];
            } else {
                return [Api::CODE_STEAM_TRADE_URL_LOADING_FAIL, []];
            }
        }
    }

    /**
     * 查询用户的创建报价
     * @param $steamId
     * @return mixed
     */
    public function checkCreatedDoing($steamId)
    {
        $where = array(
            'steam_id' => $steamId,
        );

        $whereIn = array(
            FromTradeModel::$tradeOfferStatusMap['create'],
            FromTradeModel::$tradeOfferStatusMap['waiting'],
        );

        return FromTradeModel::where($where)->whereIn('tradeoffer_status', $whereIn)->count();
    }

    /**
     * 创建存入
     * @param $steamId
     * @param $tradeUrl
     * @param $o_ids
     * @param $appId
     * @return array
     */
    public function createFrom($steamId, $tradeUrl, $o_ids, $appId)
    {
        $bot = DologinService::getInstance()->getLiveBotInfo();
        if (empty($bot)) {
            return [Api::CODE_FROM_TRADE_BOT_RETRY, []];
        }
        $clientNo = $bot['client_no'];
        $botId = $bot['bot_id'];

        list($code, $result) = $this->rpcCheckTradeUrl($tradeUrl, $steamId, $clientNo, $botId);
        if ($code != Api::CODE_OK) {
            return [$code, []];
        }

        if ($bot['can_from'] == 2) {
            return [Api::CODE_STEAM_TRADE_URL_SERVICE_BUSY, []];
        }

        $assentItems = [];
        $quantity = 0;
        foreach ($o_ids as $one) {
            $quantity += 1;
            $tmp = [];
            $tmp['o_id'] = $one;
            $tmp['bot_id'] = $botId;
            $tmp['app_id'] = $appId;
            $assentItems[] = $tmp;
        }
        $orderVerifyCode = StringHelper::getRandomCode();
        $tradeMsg = "{$orderVerifyCode}";
        $data['steam_id'] = $steamId;
        $data['app_id'] = $appId;
        $data['bot_id'] = $botId;
        $data['tradeToken'] = $result['tradeToken'];
        $data['quantity'] = $quantity;
        $data['tradeoffer_id'] = -1;
        $data['tradeoffer'] = $tradeMsg;
        $data['detail_items'] = $assentItems;
        $fromTradeId = FromTradeModel::createTradeOffer($data);
        $message = "正在安排交易{$bot['bot_name']}存入物品{$quantity}件，验证码：{$orderVerifyCode}，请在回应报价前核实交易信息";

        $result = [
            'fromTradeId' => $fromTradeId,
            'bot_id' => $botId,
            'tradeoffer' => $tradeMsg,
            'quantity' => $quantity,
            'status' => -1,
            'message' => $message,
            'leftTime' => 0
        ];
        return [Api::CODE_OK, $result];
    }

    public function createOut($steamId, $tradeUrl, $list)
    {
        $quantity = 0;
        foreach($list as $v){
            $quantity+=count($v['oids']);
        }
        if($quantity>200){
            return [Api::CODE_OUT_TRADE_ITEM_COUNT, []];
        }

        list($code, $result) = $this->rpcCheckTradeUrl($tradeUrl, $steamId);
        if ($code != Api::CODE_OK) {
            return [$code, []];
        }
        $tradeOfferIds = [];
        foreach ($list as $value){
            $bot = BotsModel::find($value['bot_id']);
            if($bot['can_out'] == 2){
                continue;
            }
            $quantity = count($value);
            $assentItems = $value['oids'];
            $orderVerifyCode = StringHelper::getRandomCode();
            $queueName = $this->getConfirmTradeQueue($value['bot_id']);

            $data['bot_id'] = $value['bot_id'];
            $data['steam_id'] = $steamId;
            $data['steam_token'] = $result['tradeToken'];
            $data['quantity'] = $quantity;
            $data['tradeoffer_id'] = -1;
            $data['tradeoffer'] = $orderVerifyCode;
            $data['queue_name'] = $queueName;
            $data['detail_items'] = $assentItems;
            $outTradeId = OutTradeModel::createTradeOffer($data);
            $message = "正在安排交易{$bot['bot_name']}取出物品{$quantity}件，验证码：{$orderVerifyCode}，请在回应报价前核实交易信息";
            if(!empty($outTradeId)){
                $tradeOfferIds[] = array(
                    "tradeofferId"=>$data['tradeoffer_id'],
                    "message"  => $message,
                    'leftTime'=>0,
                    "status"  => -1,
                    'outTradeId'=>$outTradeId
                );
            }
        }
        return [Api::CODE_OK, $tradeOfferIds];
    }

    /**
     * rpc检测交易链接
     * @param $tradeUrl
     * @param string $clientNo
     * @param int $botId
     * @return array
     */
    public function rpcCheckTradeUrl($tradeUrl, $steamId, $clientNo='', $botId=0){
        $urlArr = CommonConf::$nodeUrlArr;

        if ($clientNo) {
            $url = $urlArr[strtolower($clientNo)] . '/LAN/checkTradeurl';
        } else {
            $rand = array_rand($urlArr);
            $url = $urlArr[$rand] . '/LAN/checkTradeurl';
        }

        $param = array(
            'tradeUrl'=>$tradeUrl,
            'steamId'=>$steamId,
            'botId'=>$botId,
        );

        $res = Curl::http_post($url, SignService::getInstance()->initParamPost($param));
        $res = json_decode($res, true);

        if($res['code'] == Api::CODE_OK){
            return [Api::CODE_OK, $res['result']];
        }else{
            return [$res['code'], []];
        }
    }

    public function getStatusForFromTrade()
    {

    }

    public function getConfirmTradeQueue($botId = 0){
        //work_gearman todo
        $bot = BotsModel::find($botId);
        if(!empty($bot) && !empty($bot->client_no)){
            return 'confirmtradejob_'.$bot->client_no;
        }
        //如果机器人是在A机器,那么队列名称,例如:confirmtradejob_A confirmtradejob_B
        return self::$confirmtradejobList[mt_rand(0, count(self::$confirmtradejobList) - 1)];
    }
    
    public function getFromTradeInfo($fromTradeId)
    {
        $fromTradeVo = FromTradeModel::getFromTradeInfo($fromTradeId);
        if(empty($fromTradeVo)){
            return false;
        }
        $arr = [];
        $arr['bot_id'] = $fromTradeVo->bot_id;
        $arr['tradeoffer_id'] = $fromTradeVo->tradeoffer_id;
        $arr['tradeoffer_status'] = $fromTradeVo->tradeoffer_status;
        if($fromTradeVo->tradeoffer_status == FromTradeModel::$tradeOfferStatusMap['success']){
            $items = [];
            foreach($fromTradeVo->fromTradeDetail as $v){
                $items[] = [
                    'old_oid' => $v['o_id'],
                    'new_oid' => $v['new_assetid'],
                    'app_id' => $v['app_id'],
                    'bot_id' => $v['bot_id'],
                    'context_id' => $v['context_id'],
                    'class_id' => $v['class_id'],
                    'instance_id' => $v['instance_id'],
                ];
            }
            $arr['details'] = $items;
        }
        return $arr;
    }

    public function getOutTradeInfo($outTradeId){
        $ouTradeVo = OutTradeModel::getOutTradeByOutTradeId($outTradeId);
        if(empty($ouTradeVo)){
            return false;
        }
        $arr['tradeoffer_id'] = $ouTradeVo['tradeoffer_id'];
        $arr['tradeoffer_status'] = $ouTradeVo['tradeoffer_status'];
        return $arr;
    }
}